Clase 11: Algunas mejoras a los códigos para simular y optimizar portafolios

Juan Diego Sánchez Torres,

Profesor, MAF ITESO

  • Departamento de Matemáticas y Física
  • dsanchez@iteso.mx
  • Tel. 3669-34-34 Ext. 3069
  • Oficina: Cubículo 4, Edificio J, 2do piso

1. Motivación

En primer lugar, para poder bajar precios y información sobre opciones de Yahoo, es necesario cargar algunos paquetes de Python. En este caso, el paquete principal será Pandas. También, se usarán el Scipy y el Numpy para las matemáticas necesarias y, el Matplotlib y el Seaborn para hacer gráficos de las series de datos. Finalmente, se usará el paquete cvxopt para optimización convexa, para instalar ingrese en terminal la instrucción: conda install -c anaconda cvxopt


In [1]:
#importar los paquetes que se van a usar
import pandas as pd
import numpy as np
import datetime
from datetime import datetime
import scipy.stats as stats
import scipy as sp
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn.covariance as skcov
import cvxopt as opt
from cvxopt import blas, solvers
solvers.options['show_progress'] = False
%matplotlib inline
pd.set_option('display.notebook_repr_html', True)
pd.set_option('display.max_columns', 6)
pd.set_option('display.max_rows', 10)
pd.set_option('display.width', 78)
pd.set_option('precision', 3)
#Funciones para portafolios
import portfolio_func

2. Uso de Pandas para descargar datos de precios de cierre

Una vez cargados los paquetes, es necesario definir los tickers de las acciones que se usarán, la fuente de descarga (Yahoo en este caso, pero también se puede desde Google) y las fechas de interés. Con esto, la función DataReader del paquete pandas_datareader bajará los precios solicitados.

Nota: Usualmente, las distribuciones de Python no cuentan, por defecto, con el paquete pandas_datareader. Por lo que será necesario instalarlo aparte. El siguiente comando instala el paquete en Anaconda: conda install -c conda-forge pandas-datareader


In [2]:
assets = ['AAPL','MSFT','AA','AMZN','KO','QAI']
closes = portfolio_func.get_historical_closes(assets, '2016-01-01', '2017-10-01')

3. Formulación del riesgo de un portafolio y simulación Montecarlo


In [3]:
daily_returns=portfolio_func.calc_daily_returns(closes)

In [4]:
r=0.0001
results_frame = portfolio_func.sim_mont_portfolio(daily_returns,100000,r)


C:\Users\DSANCHEZ\AppData\Local\Continuum\Anaconda3\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools

In [5]:
#Sharpe Ratio
max_sharpe_port = results_frame.iloc[results_frame['Sharpe'].idxmax()]
#Menor SD
min_vol_port = results_frame.iloc[results_frame['SD'].idxmin()]

In [6]:
plt.scatter(results_frame.SD,results_frame.Returns,c=results_frame.Sharpe,cmap='RdYlBu')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port[1],max_sharpe_port[0],marker=(5,1,0),color='r',s=1000);
#Menor SD
plt.scatter(min_vol_port[1],min_vol_port[0],marker=(5,1,0),color='g',s=1000);



In [7]:
pd.DataFrame(max_sharpe_port)


Out[7]:
41422
Returns 0.224
SD 0.119
Sharpe 1.874
AA 0.071
AAPL 0.264
AMZN 0.158
KO 0.339
MSFT 0.064
QAI 0.104

In [8]:
pd.DataFrame(min_vol_port)


Out[8]:
64427
Returns 0.112
SD 0.077
Sharpe 1.450
AA 0.019
AAPL 0.006
AMZN 0.076
KO 0.220
MSFT 0.062
QAI 0.617

4. Optimización de portafolios


In [9]:
N=5000
results_frame_optim = portfolio_func.optimal_portfolio(daily_returns,N,r)

In [10]:
#Montecarlo
plt.scatter(results_frame.SD,results_frame.Returns,c=results_frame.Sharpe,cmap='RdYlBu')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Markowitz
plt.plot(results_frame_optim.SD, results_frame_optim.Returns, 'b-o');



In [11]:
#Sharpe Ratio
max_sharpe_port_optim = results_frame_optim.iloc[results_frame_optim['Sharpe'].idxmax()]
#Menor SD
min_vol_port_optim = results_frame_optim.iloc[results_frame_optim['SD'].idxmin()]

In [12]:
#Markowitz
plt.scatter(results_frame_optim.SD,results_frame_optim.Returns,c=results_frame_optim.Sharpe,cmap='RdYlBu');
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port_optim[1],max_sharpe_port_optim[0],marker=(5,1,0),color='r',s=1000);
#SD
plt.scatter(min_vol_port_optim[1],min_vol_port_optim[0],marker=(5,1,0),color='g',s=1000);



In [13]:
pd.DataFrame(max_sharpe_port_optim)


Out[13]:
2221
Returns 0.213
SD 0.113
Sharpe 1.876
AA 0.059
AAPL 0.239
AMZN 0.146
KO 0.339
MSFT 0.075
QAI 0.142

In [14]:
pd.DataFrame(min_vol_port_optim)


Out[14]:
4999
Returns 0.090
SD 0.074
Sharpe 1.224
AA 0.002
AAPL 0.043
AMZN 0.007
KO 0.215
MSFT 0.021
QAI 0.711

Inclusión de un bono


In [15]:
results_frame_optim_b = portfolio_func.optimal_portfolio_b(daily_returns,10000,r,0.000001)

In [16]:
#Sharpe Ratio
max_sharpe_port_optim_b = results_frame_optim_b.iloc[results_frame_optim_b['Sharpe'].idxmax()]
#Menor SD
min_vol_port_optim_b = results_frame_optim_b.iloc[results_frame_optim_b['SD'].idxmin()]

In [17]:
pd.DataFrame(max_sharpe_port_optim_b)


Out[17]:
9999
Returns 6.209e-04
SD 1.983e-04
Sharpe 2.627e+00
AA 9.972e-05
AAPL 3.644e-04
AMZN 2.219e-04
KO 5.769e-04
MSFT 1.889e-04
QAI 5.041e-04
BOND 9.980e-01

In [18]:
pd.DataFrame(min_vol_port_optim_b)


Out[18]:
9999
Returns 6.209e-04
SD 1.983e-04
Sharpe 2.627e+00
AA 9.972e-05
AAPL 3.644e-04
AMZN 2.219e-04
KO 5.769e-04
MSFT 1.889e-04
QAI 5.041e-04
BOND 9.980e-01

In [19]:
#Markowitz
plt.scatter(results_frame_optim_b.SD,results_frame_optim_b.Returns,c=results_frame_optim_b.Sharpe,cmap='RdYlBu');
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port_optim_b[1],max_sharpe_port_optim_b[0],marker=(5,1,0),color='r',s=1000);
#SD
plt.scatter(min_vol_port_optim_b[1],min_vol_port_optim_b[0],marker=(5,1,0),color='g',s=1000);



In [ ]: